package fr.miage.orleans.aar.modele.utils;

import fr.miage.orleans.aar.ejb.peupler.FacadePeuplerBean;
import fr.miage.orleans.aar.modele.Administrateur;
import fr.miage.orleans.aar.modele.Arbitre;
import fr.miage.orleans.aar.modele.But;
import fr.miage.orleans.aar.modele.ButMatch;
import fr.miage.orleans.aar.modele.Equipe;
import fr.miage.orleans.aar.modele.EtatMatchTour;
import fr.miage.orleans.aar.modele.EtatTournoi;
import fr.miage.orleans.aar.modele.Joueur;
import fr.miage.orleans.aar.modele.MatchTour;
import fr.miage.orleans.aar.modele.PosteJoueur;
import fr.miage.orleans.aar.modele.Tournoi;
import fr.miage.orleans.aar.modele.valueobject.ValueObjectButMatch;
import fr.miage.orleans.aar.modele.valueobject.ValueObjectMatch;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;

/**
 *
 * @author Steve Cancès <steve.cances@gmail.com>
 */
public class Peupler {

    private static boolean POSTES_CREES = false;
    private static boolean ADMIN_CREE = false;
    private static boolean ARBITRES_CREES = false;
    private static final String POSTE_JOUEUR_GARDIEN = "Gardien";
    private static final String POSTE_JOUEUR_ATTAQUANT = "Attaquant";
    private static final String POSTE_JOUEUR_DEFENSEUR = "Défenseur";
    private static final String[] POSTES_JOUEUR = {POSTE_JOUEUR_GARDIEN, POSTE_JOUEUR_ATTAQUANT, POSTE_JOUEUR_DEFENSEUR};
    private static final Map<String, PosteJoueur> MAP_POSTES_JOUEUR = new HashMap<>();

    private static final String[] NOMS = {"Martin", "Simon", "Morel", "Legrand", "Perrin", "Bernard", "Laurent", "Girard", "Garnier", "Morin", "Dubois", "Lefebvre", "Andre", "Faure", "Mathieu", "Thomas", "Michel", "Lefevre", "Rousseau", "Clement", "Robert", "Garcia", "Mercier", "Blanc", "Gauthier", "Richard", "David", "Dupont", "Guerin", "Dumont", "Petit", "Bertrand", "Lambert", "Muller", "Lopez", "Durand", "Roux", "Bonnet", "Henry", "Fontaine", "Leroy", "Vincent", "Francois", "Roussel", "Chevalier", "Moreau", "Fournier", "Martine", "Nicolas", "Robin", "Exbrayat"};
    private static final String[] PRENOMS = {"Dimitri", "Malik", "Loevan", "Lucas", "Mattéo", "Léo", "Evan", "Louis", "Tom", "Maxime", "Thomas", "Arthur", "Yanis", "Alexandre", "Théo", "Hugo", "Enzo", "Nathan", "Antoine", "Gabriel", "Clément", "Florentin", "Jules", "Baptiste", "Paul", "Alexis", "Noah", "Mathis", "Ethan", "Quentin", "Maxence", "Pierre", "Valentin", "Julien", "Romain", "Mohamed", "Adam", "Victor", "Nicolas", "Nolan", "Timéo", "Mathieu", "Tristan", "Antonin", "Lorenzo", "Anthony", "Dorian", "Kevin", "Gabin", "Jérémy", "Kyllian", "Dylan", "Thibault", "Constant", "Adrien", "Esteban", "Corentin", "Diego", "Samuel", "Florian", "Benjamin", "Mehdi", "Noë", "Rémi", "Simon", "Erwan", "Titouan", "Robin", "Bastien", "Lilian", "Martin", "Amine", "Guillaume", "Léonard", "Malo", "Élouan", "Davy", "Léon", "Renaud", "Bruno", "Timothée", "Félix", "Roméo", "Yohan", "Gilbert", "Colin", "Marwane", "Gaspard", "Aaron", "Émile", "Jordan", "Grégory", "Cédric", "Zacharis", "Adrian", "Mathéo", "Macéo", "Damien", "Steve", "Cyril"};
    private static final String[] OBJETS = {"Canapé", "Table", "Chaise", "Fauteuil", "Lampe", "Miroir", "Placard", "Armoire", "Tabouret", "Tapis", "Volet", "Rideau", "Lampadaire", "Poubelle", "Radiateur", "Multiprise", "Lampe de chevet", "Interrupteur"};
    private static final String[] COULEURS = {"rouge", "vert", "bleu", "jaune", "marron", "orange", "violet", "beige", "noir", "gris", "rose", "argent"};
    private static final String[] NOMS_EQUIPE = {"Cerise", "Banane", "Clémentine", "Coing", "Cynorrhodon", "Datte", "Figue", "Fraise", "Framboise", "Grenade", "Groseille", "Jujube", "Kaki", "Kiwi", "Lime", "Mandarine", "Marron", "Melon", "Mirabelle", "Abricot", "Airelle", "Alkékenge", "Amande", "Amélanche", "Ananas", "Arbouse", "Avocat", "Banane", "Bergamote", "Bigarade", "Brugnon", "Canneberge", "Cassis", "Cerise", "Châtaigne", "Citron", "Mûre", "Myrtille", "Nèfle", "Noisette", "Noix", "Olive", "Orange", "Pamplemousse", "Pastèque", "Pêche", "Pistache", "Plaquebière", "Poire", "Pomme", "Pomélo", "Prune", "Quetsche", "Raisin"};

    protected static String getRandomPrenom() {
	return (PRENOMS[new Random().nextInt(PRENOMS.length)]);
    }

    protected static String getRandomNom() {
	return (NOMS[new Random().nextInt(NOMS.length)]);
    }

    protected static String getRandomNomEquipe() {
	return (NOMS_EQUIPE[new Random().nextInt(NOMS_EQUIPE.length)]);
    }

    protected static String getRandomNomTournoi() {
	return (OBJETS[new Random().nextInt(OBJETS.length)] + " " + COULEURS[new Random().nextInt(COULEURS.length)]);
    }

    protected static PosteJoueur getRandomPosteJoueur() {
	String posteJoueurString = (POSTES_JOUEUR[new Random().nextInt(POSTES_JOUEUR.length)]);
	return MAP_POSTES_JOUEUR.get(posteJoueurString);
    }

    public static void creerPostes(FacadePeuplerBean facade) {
	if (!POSTES_CREES) {
	    for (String posteJoueurString : POSTES_JOUEUR) {
		PosteJoueur posteJoueur = facade.creerPosteJoueurPourBouchon(posteJoueurString);
		MAP_POSTES_JOUEUR.put(posteJoueurString, posteJoueur);
	    }
	    POSTES_CREES = true;
	}
    }

    public static void creerAdmin(FacadePeuplerBean facade, String nom, String prenom, String login, String password) {
	if (!ADMIN_CREE) {
	    Administrateur admininstrateur = facade.createAdmin(nom, prenom, login, password);
	    if (admininstrateur != null) {
		ADMIN_CREE = true;
	    }
	}
    }
    
    /**
     * Créer 10 arbitres
     * @param facade la facadePeupler
     */
    public static void creerArbitres(FacadePeuplerBean facade) {
	if (!ARBITRES_CREES) {
	    creerArbitres(facade, 10);
	    ARBITRES_CREES = true;
	}
    }

    public static Joueur creerJoueur(FacadePeuplerBean facade) {
	return creerJoueur(facade, getRandomPosteJoueur());
    }

    public static Joueur creerJoueur(FacadePeuplerBean facade, PosteJoueur posteJoueur) {
	return facade.createJoueur(getRandomNom(), getRandomPrenom(), posteJoueur);
    }

    public static Arbitre creerArbitre(FacadePeuplerBean facade) {
	return facade.createArbitre(getRandomNom(), getRandomPrenom());
    }

    public static Collection<Arbitre> creerArbitres(FacadePeuplerBean facade, int nbArbitres) {
	Collection<Arbitre> arbitres = new HashSet<>();
	for (int i = 0; i < nbArbitres; ++i) {
	    arbitres.add(creerArbitre(facade));
	}
	return arbitres;
    }

    public static Equipe creerEquipe(FacadePeuplerBean facade) {

	Collection<Joueur> joueurs = new HashSet<>();
	//création des 11 premiers joueur
	joueurs.add(creerJoueur(facade, MAP_POSTES_JOUEUR.get(POSTE_JOUEUR_GARDIEN)));
	for (int i = 0; i < 5; ++i) {
	    joueurs.add(creerJoueur(facade, MAP_POSTES_JOUEUR.get(POSTE_JOUEUR_ATTAQUANT)));
	    joueurs.add(creerJoueur(facade, MAP_POSTES_JOUEUR.get(POSTE_JOUEUR_DEFENSEUR)));
	}
	//Création des joueurs supplémentaires
	int nbJoueursSupp = new Random().nextInt(5);
	for (int i = 0; i < nbJoueursSupp; ++i) {
	    joueurs.add(creerJoueur(facade));
	}

	Equipe equipe = facade.createEquipe(getRandomNomEquipe());
	equipe = facade.addJoueursToEquipe(equipe, joueurs);
	return equipe;
    }

    public static Equipe getRandomEquipeInEquipes(FacadePeuplerBean facade, Collection<Equipe> equipes) {
	Equipe equipe = null;
	if (!equipes.isEmpty()) {
	    Collections.shuffle((List<Equipe>) equipes);
	    Equipe[] equipesArray = new Equipe[equipes.size()];
	    equipesArray = equipes.toArray(equipesArray);
	    equipe = equipesArray[0];
	}

	return equipe;
    }

    public static Tournoi creerTournoi(FacadePeuplerBean facade, int nbEquipes) {
	Tournoi tournoi = facade.creerTournoiPourBouchon(getRandomNomTournoi());
	Random random = new Random();
	for (int i = 0; i < nbEquipes; ++i) {
	    Equipe equipe = null;
	    Collection<Equipe> equipesNonInscrites = facade.getEquipesNonInscrites(tournoi.getTournoiId());
	    //System.out.println("equipesNonInscrites.size : "+equipesNonInscrites.size());
	    // On ajoute une equipe déja existante avec random (si il y a des equipes non deja inscrites)
	    if (!equipesNonInscrites.isEmpty() && random.nextBoolean()) {
		equipe = getRandomEquipeInEquipes(facade, equipesNonInscrites);
		//System.out.println("equipe deja existante : "+equipe);
	    }
	    // Si une equipe deja existante n'a pa été affectée on en créer une
	    if (equipe == null) {
		equipe = creerEquipe(facade);
	    }

	    facade.inscrireEquipeTournoi(tournoi.getTournoiId(), equipe.getEquipeId());
	}
	return tournoi;
    }

    public static Tournoi setTournoiEnCours(FacadePeuplerBean facade, int idTournoi) {
	facade.validerPreparationTournoi(idTournoi);
	Tournoi tournoi = facade.getTournoiDetailById(idTournoi);
	for (MatchTour matchTour : tournoi.getMatchs()) {
	    Collection<Arbitre> arbitres = facade.getAllArbitres();
	    Collections.shuffle((List<?>) arbitres);
	    Arbitre[] arbitresArray = new Arbitre[arbitres.size()];
	    arbitresArray = arbitres.toArray(arbitresArray);
	    Arbitre arbitre = arbitresArray[0];
	    facade.affecterArbitreMatch(matchTour.getMatchTourId(), arbitre.getPersonneId());
	    facade.commencerPremiereMiTemps(matchTour.getMatchTourId());
	    Random generator = new Random();
	    int nbButs = generator.nextInt(8) + 1;
	    for (int i = 0; i < nbButs; ++i) {
		Equipe equipe;
		Joueur joueur;
		if (generator.nextBoolean()) {
		    equipe = matchTour.getEquipeA();
		} else {
		    equipe = matchTour.getEquipeB();
		}
		Collection<Joueur> joueurs = equipe.getJoueurs();
		Collections.shuffle((List<?>) joueurs);
		Joueur[] joueursArray = new Joueur[joueurs.size()];
		joueursArray = joueurs.toArray(joueursArray);
		joueur = joueursArray[0];
		facade.addBut(matchTour.getMatchTourId(), equipe.getEquipeId(), joueur.getPersonneId(), generator.nextInt(45) + 1);

	    }
	}
	return tournoi;
    }

    public static Tournoi setTournoiEnCoursTirAuBut(FacadePeuplerBean facade, int idTournoi) {
	facade.validerPreparationTournoi(idTournoi);
	Tournoi tournoi = facade.getTournoiDetailById(idTournoi);
	for (MatchTour matchTour : tournoi.getMatchs()) {
	    Collection<Arbitre> arbitres = facade.getAllArbitres();
	    Collections.shuffle((List<?>) arbitres);
	    Arbitre[] arbitresArray = new Arbitre[arbitres.size()];
	    arbitresArray = arbitres.toArray(arbitresArray);
	    Arbitre arbitre = arbitresArray[0];
	    facade.affecterArbitreMatch(matchTour.getMatchTourId(), arbitre.getPersonneId());
	    facade.commencerPremiereMiTemps(matchTour.getMatchTourId());
	    Random generator = new Random();
	    //int nbButs = generator.nextInt(8) + 1;
	    int nbButs = 2;
	    boolean first = true;
	    for (int i = 0; i < nbButs; ++i) {
		Equipe equipe;
		Joueur joueur;
		//if (generator.nextBoolean()) {
		if (first) {
		    equipe = matchTour.getEquipeA();
		    first = false;
		} else {
		    equipe = matchTour.getEquipeB();
		}
		Collection<Joueur> joueurs = equipe.getJoueurs();
		Collections.shuffle((List<?>) joueurs);
		Joueur[] joueursArray = new Joueur[joueurs.size()];
		joueursArray = joueurs.toArray(joueursArray);
		joueur = joueursArray[0];
		//System.out.println("matchTour.getMatchTourId() : "+matchTour.getMatchTourId());
		facade.addBut(matchTour.getMatchTourId(), equipe.getEquipeId(), joueur.getPersonneId(), generator.nextInt(45) + 1);

	    }
	    facade.getFacadeAdmin().terminerPeriode(matchTour.getMatchTourId());
	    facade.getFacadeAdmin().terminerPeriode(matchTour.getMatchTourId());
	    facade.getFacadeAdmin().terminerPeriode(matchTour.getMatchTourId());
	    //matchTour.setEtatMatch(EtatMatchTour.TIR_AU_BUT);
	}
	return tournoi;
    }

    public static Tournoi creerTournoiEnCours(FacadePeuplerBean facade, int nbEquipes) {
	Tournoi tournoi = creerTournoi(facade, nbEquipes);
	tournoi = setTournoiEnCours(facade, tournoi.getTournoiId());
	return tournoi;
    }

    public static Tournoi creerTournoiEnCoursTirAuBut(FacadePeuplerBean facade, int nbEquipes) {
	Tournoi tournoi = creerTournoi(facade, nbEquipes);
	tournoi = setTournoiEnCoursTirAuBut(facade, tournoi.getTournoiId());
	return tournoi;
    }

    public static Tournoi setTournoiTermine(FacadePeuplerBean facade, int idTournoi) {
	facade.validerPreparationTournoi(idTournoi);
	Tournoi tournoi = facade.getTournoiDetailById(idTournoi);
	HashSet<Integer> matchToursATerminer = new HashSet<>();
	HashSet<Integer> matchToursTermines = new HashSet<>();

	for (MatchTour matchTour : tournoi.getMatchs()) {
	    matchToursATerminer.add(matchTour.getMatchTourId());
	}

	while (!matchToursATerminer.isEmpty()) {
	    for (Integer idMatch : matchToursATerminer) {
		setMatchPremierMiTemps(facade, idMatch);
		setMatchDeuxiemeMiTemps(facade, idMatch);
		setMatchTermineDeuxiemeMiTemps(facade, idMatch);
		matchToursTermines.add(idMatch);
	    }
	    matchToursATerminer.clear();
	    for (Integer idMatch : matchToursTermines) {
		MatchTour matchTour = facade.getFacadeGetters().getMatchTourById(idMatch);
		MatchTour matchTourEnfant = matchTour.getMatchEnfant();
		if (matchTourEnfant != null) {
		    matchToursATerminer.add(matchTourEnfant.getMatchTourId());
		}
	    }
	    matchToursTermines.clear();
	    
	    
	    //TODO REMOVE
	    for(Integer i : matchToursATerminer) {
		System.out.println("matchTourEnfantId : "+i);
	    }
	    //matchToursATerminer.clear();
	}

	return tournoi;
    }

    public static Tournoi creerTournoiTermine(FacadePeuplerBean facade, int nbEquipes) {
	Tournoi tournoi = creerTournoi(facade, nbEquipes);
	tournoi = setTournoiTermine(facade, tournoi.getTournoiId());
	return tournoi;
    }

    public static void razBdd(FacadePeuplerBean facade) {
	facade.razBdd();
    }

    public static MatchTour setMatchPremierMiTemps(FacadePeuplerBean facade, int idMatch) {
	MatchTour matchTour = facade.getFacadeGetters().getMatchTourById(idMatch);
	Tournoi tournoi = facade.getFacadeGetters().getTournoiDetailById(matchTour.getTournoi().getTournoiId());
	for (MatchTour mt : tournoi.getMatchs()) {
	    if (mt.getMatchTourId() == matchTour.getMatchTourId()) {
		matchTour = mt;
	    }
	}

	if (matchTour.getEtatMatch() == EtatMatchTour.NON_COMMENCE) {
	    Collection<Arbitre> arbitres = facade.getAllArbitres();
	    Collections.shuffle((List<?>) arbitres);
	    Arbitre[] arbitresArray = new Arbitre[arbitres.size()];
	    arbitresArray = arbitres.toArray(arbitresArray);
	    Arbitre arbitre = arbitresArray[0];
	    facade.affecterArbitreMatch(matchTour.getMatchTourId(), arbitre.getPersonneId());
	    facade.commencerPremiereMiTemps(matchTour.getMatchTourId());
	    Random generator = new Random();
	    int nbButs = generator.nextInt(3) + 1;
	    for (int i = 0; i < nbButs; ++i) {
		Equipe equipe;
		Joueur joueur;
		if (generator.nextBoolean()) {
		    equipe = matchTour.getEquipeA();
		} else {
		    equipe = matchTour.getEquipeB();
		}
		Collection<Joueur> joueurs = equipe.getJoueurs();
		Collections.shuffle((List<?>) joueurs);
		Joueur[] joueursArray = new Joueur[joueurs.size()];
		joueursArray = joueurs.toArray(joueursArray);
		joueur = joueursArray[0];
		facade.addBut(matchTour.getMatchTourId(), equipe.getEquipeId(), joueur.getPersonneId(), generator.nextInt(45) + 1);
	    }
	}
	return matchTour;
    }

    public static MatchTour setMatchDeuxiemeMiTemps(FacadePeuplerBean facade, int idMatch) {
	MatchTour matchTour = facade.getFacadeGetters().getMatchTourById(idMatch);
	Tournoi tournoi = facade.getFacadeGetters().getTournoiDetailById(matchTour.getTournoi().getTournoiId());
	for (MatchTour mt : tournoi.getMatchs()) {
	    if (mt.getMatchTourId() == matchTour.getMatchTourId()) {
		matchTour = mt;
	    }
	}

	if (matchTour.getEtatMatch() == EtatMatchTour.PREMIERE_MI_TEMPS) {
	    facade.getFacadeAdmin().terminerPeriode(matchTour.getMatchTourId());
	    Random generator = new Random();
	    int nbButs = generator.nextInt(3) + 1;
	    for (int i = 0; i < nbButs; ++i) {
		Equipe equipe;
		Joueur joueur;
		if (generator.nextBoolean()) {
		    equipe = matchTour.getEquipeA();
		} else {
		    equipe = matchTour.getEquipeB();
		}
		Collection<Joueur> joueurs = equipe.getJoueurs();
		Collections.shuffle((List<?>) joueurs);
		Joueur[] joueursArray = new Joueur[joueurs.size()];
		joueursArray = joueurs.toArray(joueursArray);
		joueur = joueursArray[0];
		facade.addBut(matchTour.getMatchTourId(), equipe.getEquipeId(), joueur.getPersonneId(), generator.nextInt(45) + 46);
	    }
	}
	return matchTour;
    }

    public static MatchTour setMatchTermineDeuxiemeMiTemps(FacadePeuplerBean facade, int idMatch) {
	MatchTour matchTour = facade.getFacadeGetters().getMatchTourById(idMatch);
	Tournoi tournoi = facade.getFacadeGetters().getTournoiDetailById(matchTour.getTournoi().getTournoiId());
	for (MatchTour mt : tournoi.getMatchs()) {
	    if (mt.getMatchTourId() == matchTour.getMatchTourId()) {
		matchTour = mt;
	    }
	}

	if (matchTour.getEtatMatch() == EtatMatchTour.DEUXIEME_MI_TEMPS) {
	    Equipe equipeA = matchTour.getEquipeA();
	    AtomicInteger nbButsA = new AtomicInteger();
	    AtomicInteger nbButsB = new AtomicInteger();
	    ValueObjectMatch vom = facade.getFacadeGettersVo().getVOMatch(idMatch);
	    for (ValueObjectButMatch but : vom.getListButs()) {
		if (but.getEquipe().getId() == equipeA.getEquipeId()) {
		    nbButsA.incrementAndGet();
		} else {
		    nbButsB.incrementAndGet();
		}
	    }
	    if (nbButsA.intValue() == nbButsB.intValue()) {
		Random generator = new Random();
		Collection<Joueur> joueurs = equipeA.getJoueurs();
		Collections.shuffle((List<?>) joueurs);
		Joueur[] joueursArray = new Joueur[joueurs.size()];
		joueursArray = joueurs.toArray(joueursArray);
		Joueur joueur = joueursArray[0];
		facade.addBut(matchTour.getMatchTourId(), equipeA.getEquipeId(), joueur.getPersonneId(), generator.nextInt(45) + 46);
	    }
	    facade.getFacadeAdmin().terminerPeriode(matchTour.getMatchTourId());
	}
	return matchTour;
    }

}
